package ucd.csi.comp30220.fall2011.oteop.sim;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

import ucd.csi.comp30220.fall2011.oteop.flight.FlightStatus;
import ucd.csi.comp30220.fall2011.oteop.flight.FlightStatusListener;
import ucd.csi.comp30220.fall2011.oteop.flight.FlightStatusSubscriber;
import ucd.csi.comp30220.fall2011.oteop.flight.impl.FlightStatusPublisher;
import ucd.csi.comp30220.fall2011.oteop.navigation.Position;

public class SimServer {
    
    private static String base;
    private static int flight = 0;
    private static FlightStatusPublisher publisher;
    
    public static void main(String[] argv) throws Exception {
        Server server = new Server(Integer.parseInt(argv[0]));
        base = argv[1];
        server.setHandler(new AbstractHandler() {
            public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
                    throws IOException, ServletException {
                response.setContentType("text/html;charset=utf-8");
                baseRequest.setHandled(true);
                try {
                    if ("GET".equals(request.getMethod())) {
                        SimServer.get(request.getPathInfo(), response.getOutputStream());
                    }
                    else if ("PUT".equals(request.getMethod())) {
                        SimServer.put(request.getParameterMap());
                        response.setStatus(HttpServletResponse.SC_OK);
                    }
                    else {
                        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
                    response.getWriter().println(e.getMessage());
                }
                response.flushBuffer();
            }
        });
        server.start();
        
        publisher = new FlightStatusPublisher();
        if (argv.length > 2) {
            FlightStatusSubscriber subscriber = new FlightStatusSubscriber();
            subscriber.addListener(new FlightStatusListener() {
                public void onStatusUpdate(FlightStatus status) {
                    System.out.println(status);
                }
            });
        }
    }
    
    private static void put(Map<String,String[]> params) throws Exception {
        publisher.publish(new FlightStatus(
            params.get("flightNumber")[0],
            new Position(Double.parseDouble(params.get("lat")[0]), Double.parseDouble(params.get("lon")[0])),
            (int) Double.parseDouble(params.get("speed")[0]),
            (int) Double.parseDouble(params.get("alt")[0]),
            Double.parseDouble(params.get("course")[0])));
    }
    
    private static void get(String path, OutputStream os) throws Exception {
        System.err.println("GET " +path);
        if ("/".equals(path)) 
            path = "/sim.html";
        byte[] buf;
        int len;
        DataInputStream in = null;
        if (path.equals("/flightNumber")) {
            synchronized (SimServer.class) {
                buf = new String("SIM-" +(++flight)).getBytes();
            }
            len = buf.length;
        } else {
            File f = new File(base +path);
            if (!f.exists()) 
                return;
            in= new DataInputStream(new FileInputStream(f));
            len= (int) f.length();
            buf= new byte[len];
            in.readFully(buf);
        }
        os.write(buf,0,len);
        os.flush();
        if (in != null)
            in.close(); 
    }
}
